/**
 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "plugins/ecmascript/runtime/js_invoker.h"

#include "plugins/ecmascript/runtime/ecma_runtime_call_info.h"
#include "plugins/ecmascript/runtime/internal_call_params.h"
#include "plugins/ecmascript/runtime/interpreter/interpreter-inl.h"
#include "plugins/ecmascript/runtime/js_tagged_value.h"
#include "plugins/ecmascript/runtime/js_thread.h"
#include "plugins/ecmascript/runtime/tagged_array-inl.h"
#include "libpandabase/utils/span.h"

namespace ark::ecmascript {
JSTaggedValue JsInvoker::Invoke([[maybe_unused]] JSThread *thread)
{
    UNREACHABLE();
}

extern "C" uint64_t InvokeBuiltinHandleException(JSThread *thread, JSTaggedValue retval)
{
    ASSERT(thread->HasPendingException());

    auto stack = StackWalker::Create(thread);
    ASSERT(stack.IsCFrame() && stack.GetCFrame().IsNative());

    // Return to caller if there is a BYPASS bridge, otherwise skip current frame
    auto prev = stack.GetCFrame().GetPrevFrame();
    if (stack.GetBoundaryFrameMethod<FrameKind::COMPILER>(prev) == FrameBridgeKind::BYPASS) {
        return retval.GetRawData();
    }
    stack.NextFrame();

    FindCatchBlockInCFrames(thread, &stack, nullptr);
    UNREACHABLE();
}

JSTaggedValue InvokeJsFunction(EcmaRuntimeCallInfo *info)
{
    return EcmaInterpreter::Execute(info);
}

}  // namespace ark::ecmascript
